home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1998 June / SGI Freeware 1998 June.iso / dist / fw_ATxgopher.idb / usr / freeware / src / xgopher.1.3 / itemList.c.z / itemList.c
C/C++ Source or Header  |  1998-01-21  |  8KB  |  426 lines

  1. /* itemList.c
  2.    routines to manage the data structures for gopher items. */
  3.  
  4.      /*---------------------------------------------------------------*/
  5.      /* Xgopher        version 1.3     08 April 1993                  */
  6.      /*                version 1.2     20 November 1992               */
  7.      /*                version 1.1     20 April 1992                  */
  8.      /*                version 1.0     04 March 1992                  */
  9.      /* X window system client for the University of Minnesota        */
  10.      /*                                Internet Gopher System.        */
  11.      /* Allan Tuchman, University of Illinois at Urbana-Champaign     */
  12.      /*                Computing and Communications Services Office   */
  13.      /* Copyright 1992, 1993 by                                       */
  14.      /*           the Board of Trustees of the University of Illinois */
  15.      /* Permission is granted to freely copy and redistribute this    */
  16.      /* software with the copyright notice intact.                    */
  17.      /*---------------------------------------------------------------*/
  18.  
  19.  
  20. #include <stdio.h>
  21.  
  22. #include "gopher.h"
  23. #include "itemList.h"
  24. #include "dir.h"
  25. #include "listP.h"
  26.  
  27. #include "osdep.h"
  28.  
  29. static    gopherItemList    unusedItems = {NULL, NULL};
  30. static    int        firstItemAlloc = TRUE;
  31.  
  32. #define FREE_ITEM_LIST_LENGTH    itemListLength(&unusedItems)
  33.  
  34.  
  35. /* Item list management routines:
  36.     initItemList(gopherItemListP)    set list pointers to indicate empty
  37.     appendItem(gopherItemListP, gopherItemP) add item to end of list
  38.     getItemN(gopherItemListP, int)    return pointer to Nth item in list
  39.     nextItem(gopherItemP)        return pointer to next item in list
  40.     removeItemN(gopherItemListP, int) delete Nth item from a list
  41.     removeItem(gopherItemListP, gopherItemP) delete given item from a list
  42.     itemListLength(gopherItemListP)    return length of item list
  43.  
  44.    for internal use only:
  45.     pushItem(gopherItemListP, gopherItemP) push item to front of list
  46.     printItemList(gopherItemListP, char *) Only defined if DEBUG is
  47.  
  48.    freeList management routines:
  49.     acquireItem()            return ptr to a gopherItem structure
  50.     releaseItem(gopherItemP)    Return a gopher item to the free list
  51.     freeItemList(gopherItemP)    return list of items to the free list
  52.  
  53.    freeList management routines (internal only):
  54.     allocGopherItem(int)        allocate N new items
  55.     releaseItems(gopherItemP)    Return items to the free list (internal)
  56. */
  57.  
  58.  
  59. /* acquireItem 
  60.     Allocate a gopher item from the free list */
  61.  
  62. gopherItemP
  63. acquireItem()
  64. {
  65.     gopherItemP    gi;
  66.  
  67.  
  68.     if (unusedItems.first == NULL) {
  69.  
  70.         /* out of gopher items.  First reclaim those that
  71.            are out of date, then allocate more if necessary */
  72.  
  73.         checkDirStack();
  74.  
  75.         if (unusedItems.first == NULL  ||
  76.                 FREE_ITEM_LIST_LENGTH < itemIncrement) {
  77.             allocGopherItem(firstItemAlloc ?
  78.                 itemStart : itemIncrement);
  79.             firstItemAlloc = FALSE;
  80.         }
  81.     }
  82.     gi = unusedItems.first;
  83.     unusedItems.first = gi->next;
  84.     if (unusedItems.first == NULL) unusedItems.last = NULL;
  85.  
  86.     gi->next = NULL;
  87.  
  88.     return gi;
  89. }
  90.  
  91.  
  92. /* initItemList 
  93.     Set the list pointers to indicate that the list is empty */
  94.  
  95. void
  96. initItemList(list)
  97. gopherItemListP    list;
  98. {
  99.     list->first = list->last = NULL;
  100.  
  101.     return;
  102. }
  103.  
  104.  
  105. /* releaseItem 
  106.     Return a cleared out gopher item to the free list */
  107.  
  108. void
  109. releaseItem(gi)
  110. gopherItemP    gi;
  111. {
  112.     if (gi != NULL)
  113.         pushItem(&unusedItems, gi);
  114.  
  115.     return;
  116. }
  117.  
  118.  
  119. /* releaseItems
  120.     Return a linked list of cleared out gopher items to the free list */
  121.  
  122. static void
  123. releaseItems(gi)
  124. gopherItemP    gi;
  125. {
  126.     gopherItemP    p;
  127.     int    n=0;
  128.  
  129.     while (gi != NULL) {
  130.         p = gi->next;
  131.         releaseItem(gi);
  132.         n++;
  133.         gi = p;
  134.     }
  135.  
  136. #ifdef NOT_USED
  137.     /* this code is a more efficient way of doing the above */
  138.  
  139.     if (gi == NULL) return;
  140.  
  141.     /* set p to point to the end of the items */
  142.  
  143.     for (p=gi; p->next != NULL; p=p->next) ;
  144.  
  145.     if (unusedItems.last == NULL) unusedItems.last = p;
  146.     p->next = unusedItems.first;
  147.     unusedItems.first = gi;
  148. #endif /* NOT_USED */
  149.  
  150.     return;
  151. }
  152.  
  153.  
  154. /* freeItemList
  155.     Return a list of gopher items to the free list and clear the
  156.     list header */
  157.  
  158. void
  159. freeItemList(list)
  160. gopherItemListP    list;
  161. {
  162.     gopherItemP    p;
  163.     int        n=0;
  164.  
  165.     if (list != NULL) {
  166.         /* if we know that they are already cleared out, we could use:
  167.             releaseItems(list->first);
  168.            but we don't, so free them one at a time. */
  169.  
  170.         gopherItemP    gi=list->first;
  171.  
  172.         while (gi != NULL) {
  173.             p = gi->next;
  174.             freeItem(gi);
  175.             n++;
  176.             gi = p;
  177.         }
  178.  
  179.         initItemList(list);
  180.     }
  181.  
  182.     return;
  183. }
  184.  
  185.  
  186. /* itemListLength
  187.     return the number of items in an item list */
  188.  
  189. int
  190. itemListLength(list)
  191. gopherItemListP    list;
  192. {
  193.     int    n;
  194.     gopherItemP    p;
  195.  
  196.     if (list == NULL) return 0;
  197.  
  198.     for (n=0, p=list->first; p != NULL; n++, p=p->next) ;
  199.  
  200.     return n;
  201. }
  202.  
  203.  
  204. /* appendItem 
  205.     append an item to the end of an item list */
  206.  
  207. void
  208. appendItem(list, gi)
  209. gopherItemListP    list;
  210. gopherItemP    gi;
  211. {
  212.     if (list == NULL || gi == NULL) return;
  213.  
  214.     if (list->last == NULL) {
  215.         list->first = list->last = gi;
  216.     } else {
  217.         list->last->next = gi;
  218.         list->last = gi;
  219.     }
  220.  
  221.     gi->next = NULL;
  222.  
  223.     return;
  224. }
  225.  
  226.  
  227. /* removeItemN 
  228.     delete the Nth item from a list.  The first item is numbered 0 */
  229.  
  230. void
  231. removeItemN(list, n)
  232. gopherItemListP    list;
  233. int        n;
  234. {
  235.     gopherItemP    p, prev;
  236.  
  237.     if (list == NULL) return;
  238.     if (n < 0) return;
  239.     if ((p = list->first) == NULL) return;
  240.  
  241.     if (n == 0) {
  242.         list->first = p->next;
  243.         if (list->last == p) list->last = NULL;
  244.         freeItem(p);
  245.     } else {
  246.         for (prev=p, p=p->next; p!= NULL; prev=p, p=p->next) {
  247.             if (--n == 0) {
  248.                 prev->next = p->next;
  249.                 if (p == list->last) list->last = prev;
  250.                 freeItem(p);
  251.                 break;
  252.             }
  253.         }
  254.     }
  255.  
  256.     return;
  257. }
  258.  
  259.  
  260. /* removeItem
  261.     delete the a given item from a list. */
  262.  
  263. void
  264. removeItem(list, gi)
  265. gopherItemListP    list;
  266. gopherItemP    gi;
  267. {
  268.     gopherItemP    p, prev;
  269.  
  270.     if (list == NULL) return;
  271.     if ((p = list->first) == NULL) return;
  272.  
  273.     if (p == gi) {
  274.         list->first = p->next;
  275.         if (list->last == p) list->last = NULL;
  276.         freeItem(p);
  277.     } else {
  278.         for (prev=p, p=p->next; p!= NULL; prev=p, p=p->next) {
  279.             if (p == gi) {
  280.                 prev->next = p->next;
  281.                 if (p == list->last) list->last = prev;
  282.                 freeItem(p);
  283.                 break;
  284.             }
  285.         }
  286.     }
  287.  
  288.     return;
  289. }
  290.  
  291.  
  292. /* getItemN 
  293.     return a pointer to the Nth item of the specified item list,
  294.     starting with number 0 */
  295.  
  296. gopherItemP
  297. getItemN(list, n)
  298. gopherItemListP    list;
  299. int        n;
  300. {
  301.     gopherItemP    p;
  302.  
  303.     if (n < 0) return NULL;  
  304.     if (list == NULL) return NULL;  
  305.  
  306.     p = list->first;
  307.     for ( ; p != NULL; p=p->next) {
  308.         if (n-- == 0) break;
  309.     }
  310.  
  311.     return p;
  312. }
  313.  
  314.  
  315. /* nextItem 
  316.     return a pointer to the next item in a list, given an existing item. */
  317.  
  318. gopherItemP
  319. nextItem(gi)
  320. gopherItemP    gi;
  321. {
  322.     if (gi == NULL) return NULL;
  323.     return gi->next;
  324. }
  325.  
  326.  
  327. /* pushItem 
  328.     push an item onto the front of a item list */
  329.  
  330. static void
  331. pushItem(list, gi)
  332. gopherItemListP    list;
  333. gopherItemP    gi;
  334. {
  335.     gi->next = list->first;
  336.     list->first = gi;
  337.     if (list->last == NULL) list->last = gi;
  338.  
  339.     return;
  340. }
  341.  
  342.  
  343. /* allocGopherItem
  344.     Allocate n new gopher items, adding them to the free list */
  345.  
  346. static void
  347. allocGopherItem(n)
  348. int    n;
  349. {
  350.     gopherItemP    gil, p;
  351.     int        i;
  352.  
  353.     if (n <= 0) return;
  354.  
  355.     if ((gil = (gopherItemP) malloc(n * sizeof(gopherItem))) == NULL) {
  356.         /* out of memory */
  357.         fprintf (stderr, "There is not enough memory to continue.\n");
  358.         exit(3);
  359.     }
  360.  
  361.     for (i=0, p=gil; i<n-1; i++, p++) {
  362.         initItemFields(p);
  363.         p->next = p+1;
  364.     }
  365.     initItemFields(p);
  366.     p->next = NULL;
  367.     releaseItems(gil);
  368.  
  369.     return;
  370. }
  371.  
  372.  
  373. /* itemInList
  374.         see if a gopher item is in an item list */
  375.  
  376. BOOLEAN
  377. itemInList(list, item)
  378. gopherItemListP    list;
  379. gopherItemP    item;
  380. {
  381.     gopherItemP    p;
  382.     BOOLEAN        same;
  383.  
  384.     if (list == NULL  ||  item == NULL) return FALSE;
  385.  
  386.     for (p = list->first; (p != item  &&  p != NULL); p=p->next) {
  387.         same = compareItem(item, p);
  388.         if (same) break;
  389.     }
  390.  
  391.     return (p != NULL);
  392. }
  393.  
  394.  
  395. #ifdef DEBUG_LIST
  396.  
  397.  
  398. /* printItemList
  399.    Print a list of gopher items for checking the list contents */
  400.  
  401. void
  402. printItemList(list, label)
  403. gopherItemListP list;
  404. char            *label;
  405. {
  406.         gopherItemP     gi;
  407.     int        i;
  408.  
  409.         if (list == NULL) fprintf(stdout, "NULL list %s\n", label);
  410.         else {
  411.                 gi = list->first;
  412.                 fprintf (stdout, "list %s:\n", label);
  413.                 while (gi != NULL) {
  414.             fprintf (stdout, "\t(");
  415.             for (i=0; i<PREFIX_LEN; i++) 
  416.                 fprintf (stdout, " %d ",
  417.                     (int)((USER_STRING_PREFIX(gi))[i]));
  418.             fprintf (stdout, ") ");
  419.                         fprintf (stdout, "(%s)\n", USER_STRING(gi));
  420.                         gi = gi->next;
  421.                 }
  422.                 fprintf (stdout, "    end of list\n");
  423.         }
  424. }
  425. #endif /* DEBUG_LIST */
  426.